#include <stdio.h>
#include <esp_log.h>
#include <u8g2.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

#include <driver/gpio.h>
#include "u8g2_esp32_hal.h"

// SDA - GPIO21
#define PIN_SDA 21
// SCL - GPIO22
#define PIN_SCL 22
#define BLINK_GPIO 2
#define BTN_GPIO 0

#define TAG "U8G2_TEST"

u8g2_t u8g2;
// 队列
QueueHandle_t btn_evt_queue;
// 是否开启taskstate
bool showTaskState = true;

void blinky(void *pvParameter)
{

    // gpio_pad_select_gpio(BLINK_GPIO);
    /* Set the GPIO as a push/pull output */
    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
    while (1)
    {
        /* Blink off (output low) */
        gpio_set_level(BLINK_GPIO, 0);
        vTaskDelay(1000 / portTICK_RATE_MS);
        /* Blink on (output high) */
        gpio_set_level(BLINK_GPIO, 1);
        vTaskDelay(1000 / portTICK_RATE_MS);
    }
}

void show_task(void *pvParameters) 
{
    TickType_t xLastWakeTime;

    // Initialise the xLastWakeTime variable with the current time.
    xLastWakeTime = xTaskGetTickCount();

    while (1)
    {
        // 如果不需要了让他关掉
        if (!showTaskState)
        {
            vTaskDelete(NULL);
            break;
        }

        u8g2_ClearBuffer(&u8g2);
        // ESP_LOGI(TAG, "u8g2_DrawBox");
        u8g2_DrawBox(&u8g2, 0, 26, 80, 6);

        // ESP_LOGI(TAG, "u8g2_SetFont");
        u8g2_SetFont(&u8g2, u8g2_font_ncenB14_tr);
        // ESP_LOGI(TAG, "u8g2_DrawStr");
        u8g2_DrawStr(&u8g2, 2, 17, "Hi nkolban!");

        u8g2_SendBuffer(&u8g2);
        vTaskDelayUntil(&xLastWakeTime, 1000 / portTICK_PERIOD_MS);

        u8g2_ClearBuffer(&u8g2);
        u8g2_SetFont(&u8g2, u8g2_font_unifont_t_chinese2);
        u8g2_DrawStr(&u8g2, 2, 17, "test page2");
        u8g2_DrawUTF8(&u8g2, 0, 40, "你好世界");
        u8g2_SendBuffer(&u8g2);

        vTaskDelayUntil(&xLastWakeTime, 1000 / portTICK_PERIOD_MS);
    }

    vTaskDelete(NULL);
}

void IRAM_ATTR gpio_isr_handler(void *arg)
{
    uint32_t gpio_num = (uint32_t)arg;
    // print("test");
    xQueueSendFromISR(btn_evt_queue, &gpio_num, NULL);
}

void set_btn()
{
    ESP_LOGI(TAG, "test");
    gpio_set_direction(BTN_GPIO, GPIO_MODE_INPUT);
    gpio_set_pull_mode(BTN_GPIO, GPIO_PULLUP_ONLY);
    gpio_set_intr_type(BTN_GPIO, GPIO_INTR_POSEDGE);

    gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1);
    gpio_isr_handler_add(BTN_GPIO, gpio_isr_handler, (void *)BTN_GPIO);
}

void byte_code_task(void *pvParameters)
{
    while (1)
    {
        // 删除自身进程
        if (showTaskState)
        {
            vTaskDelete(NULL);
            break;
        }

        ESP_LOGW(TAG, "kill other");
        vTaskDelay(3000 / portTICK_PERIOD_MS);
    }
}

void startShowTask()
{
    xTaskCreatePinnedToCore(&show_task, "show_task", 8192, NULL, 5, NULL, 1);
}

void startByteCodeTask()
{
    xTaskCreatePinnedToCore(&byte_code_task, "byte_code_task", 1024, NULL, 5, NULL, 1);
}

void btn_task(void *pvParameters)
{
    uint32_t io_num;
    while (1)
    {
        if (xQueueReceive(btn_evt_queue, &io_num, portMAX_DELAY) == pdPASS)
        {
            ESP_LOGW(TAG, "isr get: %d", io_num);
            showTaskState = !showTaskState;
            if (showTaskState)
            {
                startShowTask();
            }
            else
            {
                startByteCodeTask();
            }
        }
    }
}

void app_main(void)
{
    btn_evt_queue = xQueueCreate(10, sizeof(uint32_t));

    set_btn();

    u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;
    u8g2_esp32_hal.sda = PIN_SDA;
    u8g2_esp32_hal.scl = PIN_SCL;
    u8g2_esp32_hal_init(u8g2_esp32_hal);

    u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8g2_esp32_i2c_byte_cb, u8g2_esp32_gpio_and_delay_cb);
    // u8x8_SetI2CAddress(&u8g2.u8x8, 0x78);

    u8g2_InitDisplay(&u8g2);
    u8g2_SetPowerSave(&u8g2, 0);

    xTaskCreatePinnedToCore(&btn_task, "btn_task", 1024, NULL, 5, NULL, 0);
    xTaskCreatePinnedToCore(&blinky, "blinky", 512, NULL, 5, NULL, 0);
    startShowTask();
}
